import { DisplayObject, Matrix, Point, Sprite, Transform } from "pixi.js";
import { Display, DisplayType } from "../models/Display";
import { BoneController } from "./BoneController";
import { DisplayBorder } from "../views/DisplayBorder";
import { ItransformableItem } from "./ITransformableItem";
import { Transform as MyTransform } from "../geom/Transform";

export class DisplayController implements ItransformableItem {
    private _view!: DisplayObject;
    private _model: Display;
    private _parent: BoneController;
    private _localMatrix: Matrix = Matrix.IDENTITY;
    private _localBorderMatrix: Matrix = Matrix.IDENTITY;

    private _border!: DisplayBorder;
    private _originWidth = 0;
    private _originHeight = 0;
    private _level = 0;
    private _isSelected = false;

    constructor(model: Display, path: string, displayType: DisplayType, parent: BoneController) {
        this._model = model;
        this._parent = parent;
        this._parent.displayList.push(this);

        switch (displayType) {
            case DisplayType.Image:
                this.createImageDisplay(path);
                break;

            default:
                break;
        }
    }

    public createImageDisplay(path: string) {
        //const texture = new Texture(new BaseTexture(path));
        this._view = Sprite.from(path);
        const sprite = this._view as Sprite;
        sprite.anchor.set(0.5);

        let posX = this._parent.view.position.x;
        let posY = this._parent.view.position.y;
        this.view.position.set(posX, posY);
        this.view.zIndex = -1;

        this._border = new DisplayBorder(posX, posY, sprite.width, sprite.height);
        this._originWidth = sprite.width;
        this._originHeight = sprite.height;

        this._localBorderMatrix.identity();
        this._localBorderMatrix.translate(-this._originWidth / 2, -this._originHeight / 2);
        //this._border.visible = false;
    }

    // public updateLocalMatrix() {
    //     this.view.updateTransform();
    //     let globalMatrix = this.view.localTransform;
    //     let parentGlobalMatrix = this.parent.view.localTransform;

    //     this.localMatrix.identity();
    //     this.localMatrix.append(parentGlobalMatrix.clone().invert()).append(globalMatrix);
    //     let matrix = Matrix.IDENTITY;
    //     matrix.copyFrom(parentGlobalMatrix).append(this.localMatrix);
    // }

    public updateMatrixByLocalTransform(viewportScale: number = 1.0): void {
        const transform = this._model.transform;
        this._view.updateTransform();
        this._localMatrix.identity();
        this._localMatrix.scale(transform.scaleX, transform.scaleY);
        this._localMatrix.rotate(transform.rotation);
        this._localMatrix.translate(transform.x, transform.y);

        let parent = this.parent;
        let matrix = Matrix.IDENTITY;

        if (parent) {
            let boneTran = Transform.IDENTITY;
            matrix.copyFrom(parent.view.localTransform).append(this._localMatrix).decompose(boneTran);
            this.view.setTransform(boneTran.position.x, boneTran.position.y, boneTran.scale.x, boneTran.scale.y, boneTran.rotation, boneTran.skew.x, boneTran.skew.y);
            if (this._border) {
                this.view.updateTransform();
                matrix.identity();
                boneTran = Transform.IDENTITY;
                matrix.copyFrom(this.view.localTransform).append(this._localBorderMatrix).decompose(boneTran);

                this._border.setTransform(boneTran.position.x, boneTran.position.y, boneTran.scale.x, boneTran.scale.y, boneTran.rotation, boneTran.skew.x, boneTran.skew.y);
            }
        } else {
            let boneTran = Transform.IDENTITY;
            this._localMatrix.decompose(boneTran);
            this.view.setTransform(boneTran.position.x, boneTran.position.y, boneTran.scale.x, boneTran.scale.y, boneTran.rotation, boneTran.skew.x, boneTran.skew.y);
            if (this._border) {
                this.view.updateTransform();
                matrix.identity();
                boneTran = Transform.IDENTITY;
                matrix.copyFrom(this.view.localTransform).append(this._localBorderMatrix).decompose(boneTran);

                this._border.setTransform(boneTran.position.x, boneTran.position.y, boneTran.scale.x, boneTran.scale.y, boneTran.rotation, boneTran.skew.x, boneTran.skew.y);
            }
        }
    }

    public updateBorderView() {
        this.view.updateTransform();
        let matrix = Matrix.IDENTITY;
        let boneTran = Transform.IDENTITY;
        matrix.copyFrom(this.view.localTransform).append(this._localBorderMatrix).decompose(boneTran);
        this._border.setTransform(boneTran.position.x, boneTran.position.y, boneTran.scale.x, boneTran.scale.y, boneTran.rotation, boneTran.skew.x, boneTran.skew.y);
    }


    updateSubItems(): void {

    }


    isContainPoint(point: Point): boolean {
        return (this._view as Sprite).containsPoint(point);
    }

    get transform(): MyTransform {
        return this._model.transform;
    }

    get level(): number {
        return this._level;
    }

    selected(state: boolean): void {
        if (state) {
            this._border.tint = 0x49969b;
            this._isSelected = true;
        } else {
            this._border.tint = 0xededed;
            this._isSelected = false;
            this._border.visible = false;
        }
    }

    get name(): string {
        return "";
    }

    notifyUI(): void {

    }
    get parent(): BoneController | null {
        return this._parent;
    }

    get view(): DisplayObject {
        return this._view;
    }

    hoverEnter(): void {
        if (this._isSelected) {
            return;
        }
        this._border.visible = true;
        this._border.tint = 0xededed;
    }

    hoverLeave(): void {
        if (this._isSelected) {
            return;
        }
        this._border.visible = false;
    }

    get localMatrix() {
        return this._localMatrix;
    }

    get border() {
        return this._border;
    }
}